#include "./bsp_rtc/calendar/bsp_date.h"

#define    FEBRUARY         2
#define    STARTOFTIME      1970            /* 起始年份 默认是1970 */
#define    SECDAY           86400L          /*  一天有多少s */
#define    SECYR            (SECDAY * 365)
#define    leapyear(year)   ((year) % 4 == 0)
#define    days_in_year(a)  (leapyear(a) ? 366 : 365)
#define    days_in_month(a) (month_days[(a) - 1])

static int month_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
/*星期用文字ASCII码*/
char const *WEEK_STR[] = {"日", "一", "二", "三", "四", "五", "六"};
char const *en_WEEK_STR[] = { "Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
/*
 * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
 */
/*
* 函数名：GregorianDay
* 描述  ：计算公历
* 输入  ：无
* 输出  ：无
* 调用  ：内部调用
*/
void GregorianDay(struct rtc_time * tm)
{
    int leapsToDate;
    int lastYear;
    int day;
    int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };

    lastYear=tm->TmYear-1;

    /*计算从公元元年到计数的前一年之中一共经历了多少个闰年*/
    leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;      

     /*如若计数的这一年为闰年，且计数的月份在2月之后，则日数加1，否则不加1*/
    if((tm->TmYear%4==0) &&
       ((tm->TmYear%100!=0) || (tm->TmYear%400==0)) &&
       (tm->TmMon>2)) {
        /*
         * We are past Feb. 29 in a leap year
         */
        day=1;
    } else {
        day=0;
    }

    day += lastYear*365 + leapsToDate + MonthOffset[tm->TmMon-1] + tm->TmDay; /*计算从公元元年元旦到计数日期一共有多少天*/

    tm->TmWeek=day%7;
}

/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
 * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
 * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
 *
 * [For the Julian calendar (which was used in Russia before 1917,
 * Britain & colonies before 1752, anywhere else before 1582,
 * and is still in use by some communities) leave out the
 * -year/100+year/400 terms, and add 10.]
 *
 * This algorithm was first published by Gauss (I think).
 *
 * WARNING: this function will overflow on 2106-02-07 06:28:16 on
 * machines were long is 32-bit! (However, as time_t is signed, we
 * will already get problems at other places on 2038-01-19 03:14:08)
 *
 */
/*
* 函数名：mktimev
* 描述  ：将输入的日期结构体 rtc_time转换成功后返回为UTC时间戳
* 输入  ：tm 日期结构体的地址
* 输出  ：UTC时间戳
* 调用  ：外部调用
*/
uint32_t mktimev(struct rtc_time *CurrTm)
{
    struct rtc_time tm = *CurrTm;
    
    if (0 >= (int) (tm.TmMon -= 2)) {    /* 1..12 -> 11,12,1..10 */
        tm.TmMon += 12;        /* Puts Feb last since it has leap day */
        tm.TmYear -= 1;
    }

    return (((
        (uint32_t) (tm.TmYear/4 - tm.TmYear/100 + tm.TmYear/400 + 367*tm.TmMon/12 + tm.TmDay) +
            tm.TmYear*365 - 719499
        )*24 + tm.TmHour /* now have hours */
      )*60 + tm.TmMin /* now have minutes */
    )*60 + tm.TmSec; /* finally seconds */     
}

/*
* 函数名：ToTm
* 描述  ：将输入的时间戳 tim 转换为日期结构体 rtc_time
* 输入  ：tim UTC时间戳
* 输入  ：tm 日期结构体的地址
* 输出  ：无
* 调用  ：外部调用
*/
void ToTm(uint32_t tim, struct rtc_time * tm)
{
    register uint32_t    i;
    register long   hms, day;

    day = tim / SECDAY;            /* 有多少天 */
    hms = tim % SECDAY;            /* 今天的时间，单位s */

    /* Hours, minutes, seconds are easy */
    tm->TmHour = hms / 3600;
    tm->TmMin = (hms % 3600) / 60;
    tm->TmSec = (hms % 3600) % 60;

    /* Number of years in days */ 
    /*根据当前时间距离1970年的天数，来计算当前的年份*/
    for (i = STARTOFTIME; day >= days_in_year(i); i++) {
        day -= days_in_year(i);
    }
    tm->TmYear = i;

    /* Number of months in days left */ /*计算当前的月份*/
    if (leapyear(tm->TmYear))
    {
        days_in_month(FEBRUARY) = 29;
    }
    for (i = 1; day >= days_in_month(i); i++) {
        day -= days_in_month(i);
    }
    days_in_month(FEBRUARY) = 28;
    tm->TmMon = i;

    /* Days are what is left over (+1) from all that. *//*计算当前日期*/
    tm->TmDay = day + 1;

    /*
     * Determine the day of week
     */
    GregorianDay(tm);
    
}

